package com.mt.restaurant.service.material.impl;

import com.mt.restaurant.dao.material.CostDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.restaurant.entity.material.Cost;
import com.mt.restaurant.service.material.CostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class CostServiceBean extends BaseService implements CostService {

    private static Logger logger = LogManager.getLogger();

    @Autowired
    private CostDao costDao;

    @Resource
    private RedisTemplate<String, List<Cost>> redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 根据分页参数查询成本管理集合
     *
     * @param pageDTO 分页条件
     */
    @Override
    public PageResultDTO findCosts(PageDTO pageDTO) {
        pageDTO.setStartIndex((pageDTO.getCurrentPage() - 1) * pageDTO.getPageSize());
        //TODO:请在此校验参数的合法性
        this.validateFindCosts(pageDTO);
        List<Cost> costDTOS = this.costDao.findCosts(pageDTO);
        Long totalCount = this.costDao.findCostTotalCount(pageDTO);

        PageResultDTO pageResultDTO = new PageResultDTO();
        pageResultDTO.setTotalCount(totalCount);
        pageResultDTO.setDatas(costDTOS);

        return pageResultDTO;
    }

    @Override
    public Map<String, Object> findCostsAndCountTotal(PageDTO pageDTO) {
        pageDTO.setStartIndex((pageDTO.getCurrentPage() - 1) * pageDTO.getPageSize());
        //TODO:请在此校验参数的合法性
        this.validateFindCosts(pageDTO);
        Map<String, Object> result = new HashMap<>();
        List<Cost> costDTOS = this.costDao.findCosts(pageDTO);
        Long totalCount = this.costDao.findCostTotalCount(pageDTO);

        PageResultDTO pageResultDTO = new PageResultDTO();
        pageResultDTO.setTotalCount(totalCount);
        pageResultDTO.setDatas(costDTOS);

        double totalCost = 0;
        for (Cost cost : costDTOS) {
            totalCost += cost.getAmount() * cost.getPrice();
        }

        result.put("pageResultDto", pageResultDTO);
        result.put("totalCost", totalCost);

        return result;
    }

    /**
     * 查询全部成本管理集合
     */
    @Override
    public List<Cost> findAllCosts() {
        return this.costDao.findAllCosts();
    }

    /**
     * 查询所有成本管理集合(只提取ID 和 Name)
     */
    @Override
    public List<Cost> findAllCostsWithIdName() {
        //TODO:请在此校验参数的合法性
        this.validateFindAllCostsWithIdName();
        return this.costDao.findAllCostsWithIdName();
    }

    /**
     * 根据名称查询成本管理集合(只提取ID 和 Name)
     *
     * @param costName 名称
     */
    @Override
    public List<Cost> findCostsWithIdNameByName(String costName) {
        //TODO:请在此校验参数的合法性
        this.validateFindCostsWithIdNameByName(costName);
        //TODO:缓存取对应参数
        Set<String> keys = stringRedisTemplate.keys("searchData:Cost_where_costName_" + costName);
        List<Cost> costs = new ArrayList<>();
        if (keys.isEmpty()) {
            costs = this.costDao.findCostsWithIdNameByName(costName);
            redisTemplate.opsForValue().set("searchData:Cost_where_costName_" + costName, costs, 30, TimeUnit.DAYS);
        } else {
            costs = redisTemplate.opsForValue().get("searchData:Cost_where_costName_" + costName);
        }
        return costs;
    }

    /**
     * 根据ID查询指定的成本管理(只提取ID 和 Name)
     *
     * @param costId Id
     */
    @Override
    public Cost findCostsWithIdNameById(Long costId) {
        //TODO:请在此校验参数的合法性
        this.validateFindCostsWithIdNameById(costId);
        return this.costDao.findCostsWithIdNameById(costId);
    }

    /**
     * 根据ID查询指定的成本管理
     *
     * @param costId Id
     */
    @Override
    public Cost findCost(Long costId) {
        //TODO:请在此校验参数的合法性
        this.validateFindCost(costId);
        return this.costDao.findCost(costId);
    }

    /**
     * 根据ID查询指定的成本管理(包含外键)
     *
     * @param costId Id
     */
    @Override
    public Cost findCostWithForeignName(Long costId) {
        //TODO:请在此校验参数的合法性
        this.validateFindCostWithForeignName(costId);
        return this.costDao.findCostWithForeignName(costId);
    }

    /**
     * 新增成本管理
     *
     * @param cost 实体对象
     */
    @Override
    public Cost saveCost(Cost cost) {
        //TODO:请在此校验参数的合法性
        this.validateSaveCost(cost);
        Date createDatetime = cost.getCreateDatetime();
        //TODO:填充公共参数
        this.setSavePulicColumns(cost);
        if (createDatetime != null) {
            cost.setCreateDatetime(createDatetime);
        }
        Long rows = this.costDao.saveCost(cost);
        if (rows != 1) {
            String error = "新增保存成本管理出错，数据库应该返回1,但返回了 " + rows;
            throw new BusinessException(error);
        }
        return cost;
    }

    /**
     * 更新成本管理
     *
     * @param cost 实体对象
     */
    @Override
    public Cost updateCost(Cost cost) {
        //TODO:请在此校验参数的合法性
        this.validateUpdateCost(cost);
        cost.setCreateDatetime(new Date());

        Long rows = this.costDao.updateCost(cost);
        if (rows != 1) {
            String error = "修改保存成本管理出错，数据库应该返回1,但返回了 " + rows + ",数据可能被删除";
            throw new BusinessException(error);
        }
        return cost;
    }

    /**
     * 根据ID删除成本管理
     *
     * @param costId ID
     */
    @Override
    public void deleteCost(Long costId) {
        //TODO:请在此校验参数的合法性
        this.validateDeleteCost(costId);

        Map<Class<? extends BaseEntity>, EntityUsage> entityUsageMap = this.checkForeignEntity(Cost.class, costId);
        if (entityUsageMap != null && entityUsageMap.size() > 0) {
            StringBuilder errors = new StringBuilder();
            errors.append("计划删除的数据正在被以下数引用\n");
            for (EntityUsage entityUsage : entityUsageMap.values()) {
                errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
                for (Map.Entry<Long, String> entry : entityUsage.getUsageIdNames().entrySet()) {
                    errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
                }
            }
            errors.append("，不能删除，请检查处理后再删除");
            throw new BusinessException(errors.toString());
        }

        Long rows = this.costDao.deleteCost(costId);
        if (rows != 1) {
            String error = "删除成本管理出错，数据可能已经被删除";
            throw new BusinessException(error);
        }
    }

    //TODO:---------------验证-------------------

    private void validateFindCosts(PageDTO pageDTO) {
        //TODO:请使用下面方法添加数据过滤条件
        //		pageDTO.addFilter("creatorId",this.getLoginUserId());
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateFindCostsWithIdNameByName(String costName) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }


    private void validateFindAllCostsWithIdName() {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateFindCostsWithIdNameById(Long costId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateFindCost(Long costId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateFindCostWithForeignName(Long costId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateSaveCost(Cost cost) {
        //不为空判断
        if (cost.getEid() != null || cost.getCreatorId() != null) {
            throw new BusinessException("非法请求");
        }
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateUpdateCost(Cost cost) {
        //不为空判断
        if (cost.getEid() == null) {
            throw new BusinessException("唯一标识不能为空");
        }
        //是否存在判断
        if (this.costDao.findCostTotalCount(PageDTO.create(Cost.FIELD_ID, cost.getEid())) == 0) {
            throw new BusinessException("修改的成本管理 " + cost.getName() + " 不存在，修改失败，请重试或联系管理员");
        }
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    private void validateDeleteCost(Long costId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateCost()写法
    }

    @Override
    public boolean canDownloadAttachment(String formName, Long id) {
        return true;
    }
}
